#!/bin/bash
#  “显性守护者” by 阎兆珣 2020-7
# run command(s) at background after entering the right working directory
# execute it with a config file as argument
# with uncommented lines of the pattern:
# PATH COMMAND
# it will also record all the output of process the COMMAND started into out.log
# in that PATH as well as (re)starting time and date marks
# each COMMAND Must be Different
# 中文说明详见　Readme

if [ -z $1 ]; then echo 'Err: must put path of config file as 1st argument' & exit 3; fi

# read config file from $1, delete comment line, and analyze the paths and commands
declare -a paths
declare -a cmds
n=-1
while read -r line
do
  realLine=`echo $line | grep -v '#'`
  #echo $line 
  if [ "$realLine" ]; then
    let n++
    path=`echo $realLine| awk '{print $1}'`
    cmd=${realLine##$path}
    paths[$n]=$path
    cmds[$n]=$cmd
    #echo 'line'$i':' $line
    if [ -z "$cmd" ]; then echo 'Err: lacking COMMAND after:' "$line" & exit 3; fi
  fi
done < $1 #addtional argument to tell the path of the config file
#echo $n
if [ $n -eq -1 ]; then echo 'Err: invalid config file with no line without #' & exit 3; fi

# start real daemon

olddate=`date +'%Y/%m/%d %a'`

while true; do
  # after midnight or noon, check if it is a new day 
  now=`date +%X`
  # if hour=00 min=00 sec<10
  if [ ${now:0:2} = '00' ] & [ ${now:3:2} = '00' ] & [ $[ 10#${now:6:2} ] -le 10 ]; then 
    newdate=`date +'%Y/%m/%d %a'`
    if [ "$newdate" = "$olddate" ]; then
      newdate=''
    else
      olddate=$newdate
    fi
  fi # now $newdate being zero string becomes a trigger for further action

  # check the paths & cmds line by line
  for (( i=0; i<=$n; i++ )); do
    # curline=${config[$i]}
    # path=`echo $curline| awk '{print $1}'`
    # cmd=${curline##$path}
    path=${paths[i]}
    cmd=${cmds[i]}

    # 'mark new day'
    if [ "$newdate" ]; then
      cd $path
      echo -e '\n'DATE `date +'%Y/%m/%d %a' ` '\n' >> out.log
    fi

    # 'kill zombie process, no duplicate process allowed from the same $cmd'
    stat=`ps aux|grep "$cmd"|grep -v grep|awk {'print $8'}`
    if [[ "$stat" =~ ^[Zz] ]]; then # grammer of regular expression
      kill -9 `ps aux|grep $cmd|grep -v grep|awk {'print $2'}` 
    fi

    # "start new process if no $cmd found in 'ps aux'"
    running=`ps aux|grep "$cmd"|grep -v grep`
    #echo running $running
    if [ -z "$running" ]; then
      cd $path
      echo has entered `pwd`
      echo -e '\n'`date +'%Y/%m/%d %a, %X'`: STARTING - "$cmd" '\n' >> out.log
      newcmd="$cmd &>> out.log &" #execute $cmd in background
      eval $newcmd &
    fi
  done

  sleep 5
done
